package cn.anc.aonicardv.media;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;

import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import cn.anc.aonicardv.GlideApp;
import cn.anc.aonicardv.R;
import cn.anc.aonicardv.util.LogUtil;
import cn.anc.aonicardv.util.TimeFormatUtils;
import cn.anc.aonicardv.util.UIUtil;

/**
 * Created by yangdai on 2017/9/7.
 */

public class PlayerController extends FrameLayout implements MediaController {

    private static String TAG = "llc_PlayerController";

    private static final int sDefaultTimeout = 3000;
    private static final int FADE_OUT = 1;
    private static final int SHOW_PROGRESS = 2;
    private int playState = STATE_IDLE;
    private TextView playOptionTv,playLastTv,playNextTv;
    private TextView exitFullScreenTv;
    private TextView fullScreenTv;
    private TextView titleTv;
    private TextView currentTimeTv;
    private TextView endTimeTv;
    private SeekBar playProgressSb;
    private ProgressBar playProgressPb;
    private RelativeLayout playProgressRl;
    private LinearLayout titleLL;
    private ImageView thumbIv;
    private View mRoot;
    private Context mContext;
    private boolean mShowing;
    private MediaOperation mPlayer;
    private boolean mDragging;
    private OnShownListener mShownListener;
    private OnHiddenListener mHiddenListener;
    private OnVideoBackListener mOnVideoBackListener;
    private OnFullScreenClickListener mOnFullScreenClickListener;
    private OnPlayNextClickListener mOnPlayNextClickListener;
    private OnPlayLastClickListener mOnPlayLastClickListener;



    private OnSeekBarChangeListener mOnSeekChangeListener;
    private OnPlayStatusListener mOnPlayStatusListener;
    private OnPlayClickListener mOnPlayClickListener;
    private long mDuration;
    private String mTitle;
    private View mMediaBufferingIndicator;

    public PlayerController(@NonNull Context context) {
        super(context);
        initView(context);
    }

    private void initView(Context context) {
        mContext = context;
        mRoot = makeControllerView();
        initControllerView(mRoot);
    }

    public PlayerController(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onFinishInflate() {
        super.onFinishInflate();
        if (mRoot != null) {
            initControllerView(mRoot);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mHandler.removeMessages(SHOW_PROGRESS);
        mHandler.removeMessages(FADE_OUT);
    }

    private void initControllerView(View v) {
        fullScreenTv = v.findViewById(R.id.tv_fullscreen);
        exitFullScreenTv = v.findViewById(R.id.tv_exit_fullscreen);
        titleTv = v.findViewById(R.id.tv_title);
        playOptionTv = v.findViewById(R.id.tv_play_option);
        playLastTv = v.findViewById(R.id.tv_play_last);
        playNextTv = v.findViewById(R.id.tv_play_next);
        currentTimeTv = v.findViewById(R.id.tv_current_time);
        endTimeTv = v.findViewById(R.id.tv_end_time);
        playProgressSb = v.findViewById(R.id.sb_play_progress);
        playProgressPb = v.findViewById(R.id.pb_play_progress);
        playProgressRl = v.findViewById(R.id.rl_play_progress);


        playProgressRl.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Rect seekRect = new Rect();
                playProgressSb.getHitRect(seekRect);
                if ((event.getY() >= (seekRect.top - 500)) && (event.getY() <= (seekRect.bottom + 500))) {
                    float y = seekRect.top + seekRect.height() / 2;
                    //seekBar only accept relative x
                    float x = event.getX() - seekRect.left;
                    if (x < 0) {
                        x = 0;
                    } else if (x > seekRect.width()) {
                        x = seekRect.width();
                    }
                    MotionEvent me = MotionEvent.obtain(event.getDownTime(), event.getEventTime(),
                            event.getAction(), x, y, event.getMetaState());
                    return playProgressSb.onTouchEvent(me);
                }
                return false;
            }
        });
        titleLL = v.findViewById(R.id.ll_title);
        thumbIv = v.findViewById(R.id.iv_thumb);
        playProgressSb.setThumbOffset(1);
        playProgressSb.setMax(1000);
        playProgressSb.setOnSeekBarChangeListener(mSeekListener);
        exitFullScreenTv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mOnVideoBackListener != null)
                    mOnVideoBackListener.back();
            }
        });
        fullScreenTv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mOnFullScreenClickListener != null)
                    mOnFullScreenClickListener.onFullScreenClick();
            }
        });
        playOptionTv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                doPauseResume();
            }
        });


        playLastTv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mOnPlayLastClickListener != null)
                    mOnPlayLastClickListener.onPlayLastClick();
            }
        });
        playNextTv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mOnPlayNextClickListener != null)
                    mOnPlayNextClickListener.onPlayNextClick();
            }
        });

        requestOptionBtnFocus();
    }


    /**
     * 创建视图包含小部件,控制回放
     */
    protected View makeControllerView() {
        return ((LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
                R.layout.layout_video_player, this);
    }

    @Override
    public void show(int timeout) {
        if (!mShowing) {
            requestOptionBtnFocus();
            if (!TextUtils.isEmpty(mTitle))
                titleLL.setVisibility(VISIBLE);
            playProgressRl.setVisibility(VISIBLE);
            playProgressPb.setVisibility(GONE);
            mShowing = true;
            if (mShownListener != null) {
                mShownListener.onShown();
            }
        }
        playOptionTv.setVisibility(VISIBLE);
        playLastTv.setVisibility(VISIBLE);
        playNextTv.setVisibility(VISIBLE);
        mHandler.removeMessages(FADE_OUT);
        mHandler.sendEmptyMessage(SHOW_PROGRESS);
        if (timeout != 0) {
            mHandler.sendMessageDelayed(mHandler.obtainMessage(FADE_OUT),
                    timeout);
        }
    }

    private void requestOptionBtnFocus() {
        if (playOptionTv != null)
            playOptionTv.requestFocus();
        if (playLastTv != null)
            playLastTv.requestFocus();
        if (playNextTv != null)
            playNextTv.requestFocus();
        if (fullScreenTv != null)
            fullScreenTv.requestFocus();
        if (playProgressSb != null)
            playProgressSb.requestFocus();
    }

    @Override
    public void hide() {
        if (mShowing) {
            try {
                titleLL.setVisibility(INVISIBLE);
                playProgressRl.setVisibility(INVISIBLE);
                playOptionTv.setVisibility(INVISIBLE);
                playLastTv.setVisibility(INVISIBLE);
                playNextTv.setVisibility(INVISIBLE);
                playProgressPb.setVisibility(VISIBLE);
            } catch (IllegalArgumentException ex) {
            }
            mShowing = false;
            if (mHiddenListener != null) {
                mHiddenListener.onHidden();
            }
        }
    }

    @Override
    public boolean isShowing() {
        return mShowing;
    }

    @Override
    public void setMediaPlayer(MediaOperation player) {
        mPlayer = player;
    }

    public void setFullScreenBtnVisibility(boolean isVisibility) {
        if (isVisibility) {
            fullScreenTv.setVisibility(VISIBLE);
        } else {
            fullScreenTv.setVisibility(GONE);
        }
    }

    public void setExitFullScreenBtnVisibility(boolean isVisibility) {
        if (isVisibility) {
            exitFullScreenTv.setVisibility(VISIBLE);
        } else
            exitFullScreenTv.setVisibility(GONE);
    }

    @Override
    public void setMediaBufferingIndicator(View mediaBufferingIndicator, ViewGroup.LayoutParams layoutParams) {
        if (mediaBufferingIndicator != null) {
            if (mMediaBufferingIndicator != null)
                removeView(mMediaBufferingIndicator);
            mMediaBufferingIndicator = mediaBufferingIndicator;
            addView(mMediaBufferingIndicator, layoutParams);
        }
    }

    @Override
    public void setEnabled(boolean isEnable) {
        super.setEnabled(isEnable);
        if (playOptionTv != null) {
            playOptionTv.setEnabled(isEnable);
        }
        if (playLastTv != null) {
            playLastTv.setEnabled(isEnable);
        }
        if (playNextTv != null) {
            playNextTv.setEnabled(isEnable);
        }
        if (playProgressSb != null) {
            playProgressSb.setEnabled(isEnable);
        }
    }

    /**
     * 设置播放的文件名称
     */
    public void setTitle(String title) {
        mTitle = title;
        if (!TextUtils.isEmpty(mTitle)) {
            titleLL.setVisibility(VISIBLE);
            titleTv.setText(title);
        } else {
            titleLL.setVisibility(GONE);
        }
    }

    public void setThumbnail(String url) {
        LogUtil.e(TAG,"---------setThumbnail--------:");
        if (!TextUtils.isEmpty(url)) {
            GlideApp.with(getContext()).load(url).placeholder(R.mipmap.image_loading).into(new SimpleTarget<Drawable>() {
                @Override
                public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                    thumbIv.setImageDrawable(resource);
                }
            });
        }
    }

    public void updateControllerState(int state) {
        LogUtil.e(TAG,"---------点击--------:");
        if (state == STATE_PLAYING || state == STATE_RESUME) {
            LogUtil.e(TAG,"------------state == STATE_PLAYING || state == STATE_RESUME-----:"+state);
            if (state == STATE_PLAYING) {
                LogUtil.e(TAG,"updateControllerState:STATE_PLAYING");
                playState = STATE_PLAYING;
            } else
                playState = STATE_RESUME;
            thumbIv.setVisibility(GONE);
            if (playOptionTv != null) {
                LogUtil.e(TAG,"updateControllerState:pause");
                playOptionTv.setBackgroundResource(R.mipmap.pause);
            }
        } else if (state == STATE_IDLE) {
            LogUtil.e(TAG,"updateControllerState:STATE_IDLE");
            playState = STATE_IDLE;
            thumbIv.setVisibility(VISIBLE);
            playOptionTv.setVisibility(VISIBLE);
            playLastTv.setVisibility(VISIBLE);
            playNextTv.setVisibility(VISIBLE);
            playProgressSb.setProgress(0);
            if (playOptionTv != null) {
                playOptionTv.setBackgroundResource(R.mipmap.play);
            }
            if (mMediaBufferingIndicator != null) {
                mMediaBufferingIndicator.setVisibility(GONE);
            }
            mHandler.removeMessages(FADE_OUT);
            show(0);
        }
        if (state == STATE_PREPARING) {
            LogUtil.e(TAG,"updateControllerState:STATE_PREPARING");
            playState = STATE_PREPARING;
            thumbIv.setVisibility(GONE);
            playLastTv.setVisibility(GONE);
            playNextTv.setVisibility(GONE);

            playOptionTv.setVisibility(GONE);
            if (mMediaBufferingIndicator != null) {
                mMediaBufferingIndicator.setVisibility(VISIBLE);
            }
        } else if (state == STATE_PAUSED) {
            playState = STATE_PAUSED;
            if (playOptionTv != null) {
                playOptionTv.setBackgroundResource(R.mipmap.play);
            }
        }
    }

    private long setProgress() {
        if (mPlayer == null || mDragging) {
            return 0;
        }
        int position = mPlayer.getCurrentPosition();
        int duration = mPlayer.getDuration();
        if (duration > 0) {
            long pos = 1000L * position / duration;
            if (isShowing() && playProgressSb != null){
                playProgressSb.setProgress((int) pos);
            }
            if (!isShowing() && playProgressPb != null){
                playProgressPb.setProgress((int) pos);
            }
        }
        int percent = mPlayer.getBufferPercentage();
        LogUtil.e(TAG,"mPlayer.getBufferPercentage:percent:"+percent);
        if (isShowing() && playProgressSb != null)
            playProgressSb.setSecondaryProgress(percent * 10);
        if (!isShowing() && playProgressPb != null)
            playProgressPb.setSecondaryProgress(percent * 10);

        mDuration = duration;
        if (endTimeTv != null) {
            endTimeTv.setText(TimeFormatUtils.formatTime(mDuration));
        }
        if (currentTimeTv != null) {
            currentTimeTv.setText(TimeFormatUtils.formatTime((long) position));
        }
        return position;
    }


    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            long pos;
            switch (msg.what) {
                case FADE_OUT:
                    hide();
                    break;
                case SHOW_PROGRESS:
                    pos = setProgress();
                    if (!mDragging) {
                        msg = obtainMessage(SHOW_PROGRESS);
                        sendMessageDelayed(msg, 1000 - (pos % 1000));
                    }
                    break;
            }
        }
    };

    private void doPauseResume() {
        LogUtil.e("llcTest","--------------:playState"+playState);
        if (playState == STATE_PLAYING || playState == STATE_RESUME) {
            mPlayer.pause();
            if (mOnPlayStatusListener != null)
                mOnPlayStatusListener.onPlayStatus(STATE_PAUSED);
        } else if (playState == STATE_PAUSED) {
            mPlayer.resume();
            if (mOnPlayStatusListener != null)
                mOnPlayStatusListener.onPlayStatus(STATE_RESUME);
        } else if (playState == STATE_IDLE) {
            boolean isPlay = true;
            if (mOnPlayClickListener != null) {
                isPlay = !mOnPlayClickListener.onPlayClick();
            }
            if (isPlay) {
                mPlayer.start();
                if (mOnPlayStatusListener != null)
                    mOnPlayStatusListener.onPlayStatus(STATE_PLAYING);
            }
        } else if (playState == STATE_COMPLETE) {
            boolean isPlay = true;
            if (mOnPlayClickListener != null) {
                isPlay = !mOnPlayClickListener.onPlayClick();
            }
            if (isPlay) {
                mPlayer.start();
                if (mOnPlayStatusListener != null)
                    mOnPlayStatusListener.onPlayStatus(STATE_PLAYING);
            }
        }
    }



    private SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
        public void onStartTrackingTouch(SeekBar bar) {
            LogUtil.e(TAG,"---------onStartTrackingTouch--------:");
            if (mOnSeekChangeListener != null)
                mOnSeekChangeListener.onStartTrackingTouch(bar);
            mDragging = true;
            if (mMediaBufferingIndicator != null && mMediaBufferingIndicator.getVisibility() != VISIBLE)
                show(3600000);
            mHandler.removeMessages(SHOW_PROGRESS);
        }

        public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
            if (mOnSeekChangeListener != null)
                mOnSeekChangeListener.onProgressChanged(bar, progress, fromuser);
            if (!fromuser) {
                return;
            }
            final long newposition = (mDuration * progress) / 1000;
            String time = TimeFormatUtils.formatTime(newposition);
            if (currentTimeTv != null) {
                currentTimeTv.setText(time);
            }
        }

        public void onStopTrackingTouch(SeekBar bar) {
            mPlayer.seekTo((mDuration * bar.getProgress()) / 1000);
            if (mOnSeekChangeListener != null)
                mOnSeekChangeListener.onStopTrackingTouch(bar);
            if (mMediaBufferingIndicator != null && mMediaBufferingIndicator.getVisibility() != VISIBLE)
                show(sDefaultTimeout);
            mHandler.removeMessages(SHOW_PROGRESS);
            mDragging = false;
            mHandler.sendEmptyMessageDelayed(SHOW_PROGRESS, 1000);
        }
    };

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        int keyCode = event.getKeyCode();
        if (event.getRepeatCount() == 0
                && (keyCode == KeyEvent.KEYCODE_HEADSETHOOK
                || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_SPACE)) {
            doPauseResume();
            show(sDefaultTimeout);
            requestOptionBtnFocus();
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP) {
            if (mPlayer.isPlaying()) {
                mPlayer.pause();
                updateControllerState(STATE_IDLE);
            }
            return true;
        } else {
            show(sDefaultTimeout);
        }
        return super.dispatchKeyEvent(event);
    }



    public void setOnShownListener(OnShownListener l) {
        mShownListener = l;
    }

    public void setOnHiddenListener(OnHiddenListener l) {
        mHiddenListener = l;
    }

    public void setOnPlayLastClickListener(OnPlayLastClickListener onPlayLastClickListener) {
        mOnPlayLastClickListener = onPlayLastClickListener;
    }
    public void setOnPlayNextClickListener(OnPlayNextClickListener onPlayNextClickListener) {
        mOnPlayNextClickListener = onPlayNextClickListener;
    }
    public void setOnFullScreenClickListener(OnFullScreenClickListener onFullScreenClickListener) {
        mOnFullScreenClickListener = onFullScreenClickListener;
    }

    public void setOnVideoBackListener(OnVideoBackListener onVideoBackListener) {
        mOnVideoBackListener = onVideoBackListener;
    }

    public void setOnSeekChangeListener(OnSeekBarChangeListener mSeekListener) {
        mOnSeekChangeListener = mSeekListener;
    }

    public void setOnPlayStatusListener(OnPlayStatusListener onPlayStatusListener) {
        mOnPlayStatusListener = onPlayStatusListener;
    }

    public void setOnPlayClickListener(OnPlayClickListener onPlayClickListener) {
        mOnPlayClickListener = onPlayClickListener;
    }

    public interface OnPlayLastClickListener {
        void onPlayLastClick();
    }

    public interface OnPlayNextClickListener {
        void onPlayNextClick();
    }
    public interface OnFullScreenClickListener {
        void onFullScreenClick();
    }

    public interface OnPlayClickListener {
        boolean onPlayClick();
    }

    public interface OnPlayStatusListener {
        void onPlayStatus(int status);
    }

    public interface OnShownListener {
        void onShown();
    }

    public interface OnHiddenListener {
        void onHidden();
    }

    public interface OnSeekBarChangeListener {

        void onProgressChanged(SeekBar bar, int progress, boolean fromuser);

        void onStartTrackingTouch(SeekBar var1);

        void onStopTrackingTouch(SeekBar var1);
    }

    public interface OnVideoBackListener {
        void back();
    }
}
